#include "Consulta.h"

Consulta::Consulta(int cantidadEstacionamientos):
	detectando (true),
	cantidadEstacionamientos (cantidadEstacionamientos),
	colaAdministrador (Cola<MensajeTicket>((char*) ARCHIVO_COLA_ADMINISTRADOR, 1)){

	SignalHandler::getInstance()->registrarHandler(SIGUSR1, this);
	SignalHandler::getInstance()->registrarHandler(SIGINT, this);
	SignalHandler::getInstance()->registrarHandler(SIGTERM, this);

	Log::getInstance()->loguear("Consulta: creada.");
}

Consulta::~Consulta() {
	SignalHandler::getInstance()->removerHandler(SIGUSR1);
	SignalHandler::getInstance()->removerHandler(SIGINT);
	SignalHandler::getInstance()->removerHandler(SIGTERM);
	SignalHandler::destruir();

	Log::getInstance()->loguear("Consulta: destruida.");
}

/**
 * Handler de señales:
 * SIGUSR1: Señal que envia el terminador para finalizar la simulación.
 * SIGINT: Se ignora. El terminador la toma para iniciar la detención del programa ordenadamente
 * SIGTERM: Se ignora.  El terminador la toma para iniciar la detención del programa ordenadamente
 */
int Consulta::handleSignal(int signum){
	if (signum == SIGUSR1){
		Log::getInstance()->loguear("Consulta: me llego SIGUSR1. Voy a finalizar.");
		this->detectando = false;

	} else if (signum == SIGINT){
		Log::getInstance()->loguear("Consulta: me llego SIGINT. No hago nada.");
		// La señal la toma el terminador para detener la ejecución ordenadamente.

	} else if (signum == SIGTERM){
		Log::getInstance()->loguear("Consulta: me llego SIGTERM. No hago nada.");
		// La señal la toma el terminador para detener la ejecución ordenadamente.

	}
	return 0;
}

/**
 * Metodo que espera el ingreso de una consulta por parte del usuario.
 */
void Consulta::iniciarDeteccion() {
	char tecla;
	int numeroEstacionamiento;
	string linea;

	while(this->detectando){

		getline(std::cin, linea);
		std::istringstream ss(linea);

		tecla = 0;
		numeroEstacionamiento = -1;
		ss >> tecla;
		ss >> numeroEstacionamiento;

		if (numeroEstacionamiento < -1 || numeroEstacionamiento >= this->cantidadEstacionamientos){
			numeroEstacionamiento = -1;
		}

		if (tecla == TECLA_CANTIDAD){
			this->consultarCantidadAutos(numeroEstacionamiento);
		} else if (tecla == TECLA_MONTO){
			this->consultarMontoFacturado(numeroEstacionamiento);
		}
	}
}

/**
 * Envia un mensaje al administrador solicitandole la cantidad de autos de uno
 * o todos los estacionamientos.
 * Luego lee de la cola de mensajes la respuesta del adminitrador.
 */
void Consulta::consultarCantidadAutos(int numeroEstacionamiento){
	MensajeTicket mensaje;
	mensaje.mtype = CONSULTA_CANTIDAD_AUTOS_P;
	mensaje.ticket.setNumeroEstacionamiento(numeroEstacionamiento);
	this->colaAdministrador.escribir(mensaje);

	if (numeroEstacionamiento == -1){
		// Se consulta por la cantidad de autos de todos los estacionamientos.
		for (int i = 0; i < this->cantidadEstacionamientos; i++){
			this->colaAdministrador.leer(CONSULTA_CANTIDAD_AUTOS_R, &mensaje);
			this->imprimirCantidadAutos(mensaje.ticket.getNumeroEstacionamiento(), mensaje.ticket.getLugarOcupado());
		}
	} else {
		// Se consulta por un solo estacionamiento.
		this->colaAdministrador.leer(CONSULTA_CANTIDAD_AUTOS_R, &mensaje);
		this->imprimirCantidadAutos(mensaje.ticket.getNumeroEstacionamiento(), mensaje.ticket.getLugarOcupado());
	}

}

/**
 * Envia un mensaje al administrador solicitandole el monto facturado por uno
 * o todos los estacionamientos.
 * Luego lee de la cola de mensajes la respuesta del adminitrador.
 */
void Consulta::consultarMontoFacturado(int numeroEstacionamiento){
	MensajeTicket mensaje;
	mensaje.mtype = CONSULTA_MONTO_FACTURADO_P;
	mensaje.ticket.setNumeroEstacionamiento(numeroEstacionamiento);
	this->colaAdministrador.escribir(mensaje);

	if (numeroEstacionamiento == -1){
		// Se consulta por el monto facturado de todos los estacionamientos.
		for (int i = 0; i < this->cantidadEstacionamientos; i++){
			this->colaAdministrador.leer(CONSULTA_MONTO_FACTURADO_R, &mensaje);
			this->imprimirMontoFacturado(mensaje.ticket.getNumeroEstacionamiento(), mensaje.ticket.getLugarOcupado());
		}
	} else {
		// Se consulta por un solo estacionamiento.
		this->colaAdministrador.leer(CONSULTA_MONTO_FACTURADO_R, &mensaje);
		this->imprimirMontoFacturado(mensaje.ticket.getNumeroEstacionamiento(), mensaje.ticket.getLugarOcupado());
	}

}

/**
 * Muestra por pantalla la cantidad de autos de un estacionamiento.
 */
void Consulta::imprimirCantidadAutos(int numeroEstacionamiento, int cantidadAutos){
	Log::getInstance()->imprimir("La cantidad de autos en el estacionamiento "
		+ intToString(numeroEstacionamiento)
		+ " es " + intToString(cantidadAutos) + ".");
}

/**
 * Muestra por pantalla el monto facturado por un estacionamiento.
 */
void Consulta::imprimirMontoFacturado(int numeroEstacionamiento, int montoFacturado){
	Log::getInstance()->imprimir("El monto facturado hasta el momento en el estacionamiento "
		+ intToString(numeroEstacionamiento)
		+ " es $" + intToString(montoFacturado) + ".");
}
